package com.vagavaga.tx;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;

/**
 * Intercepts all nested transaction methods on {@link Connection}. This
 * is used so that after acquiring transaction calling thread will not be
 * able to create another transaction, but will join existing transaction.
 *
 * @author <code>river</code>
 * @version $Revision: 1.7 $ $Date: 2004/11/07 00:00:27 $
 */
class ChildTransactionInterceptor extends TxInterceptor {
    private final String dsName;
    
    public ChildTransactionInterceptor(String dsName) {
        if (dsName == null) throw new IllegalArgumentException("data source name must be set.");
        this.dsName = dsName;
    }
    /**
     * Implementation of invoke method specified in InvocationHandler.
     * @param object the proxy instance that the method was invoked on
     * @param method method the <code>Method</code> instance corresponding to
     * the interface method invoked on the proxy instance.
     * @param objectArray an array of objects containing the values of the
     * arguments passed in the method invocation on the proxy instance,
     * or <code>null</code> if interface method takes no arguments.
     * @return the value to return from the method invocation on the
     * proxy instance.
     * @throws Throwable the exception to throw from the method
     * invocation on the proxy instance.
     */
    public Object invoke(Object object, Method method, Object[] objectArray) throws Throwable {
        if (AUTOCOMMIT_METHOD.equals(method)
                || SET_ISOLATION_METHOD.equals(method)
                || COMMIT_METHOD.equals(method)
                || CLOSE_METHOD.equals(method)) {
            return null;
        } else if (ROLLBACK_METHOD.equals(method)) {
            // set rollback only for current transaction
            TransactionManager.getCurrentTransaction(dsName).setRollbackOnly();
            return null;
        }
        try {
            Connection c = TransactionManager.getCurrentTransaction(dsName).
                    getConnection();
            return method.invoke(c, objectArray);
        } catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}
